#ifndef POOL_H_
#define POOL_H_

#include <sdfs/common/PoolInterface.h>
#include <sdfs/common/PoolData.h>

#include <vector>

#include <boost/shared_ptr.hpp>

#include <muduo/base/Types.h>
#include <muduo/base/Logging.h>
#include <muduo/base/Mutex.h>

using namespace boost;
using namespace muduo;

namespace sdfs
{
namespace common
{

template <typename T>
class Pool: public PoolInterface<T>
{
public:
	Pool(int poolsize):enableReturn_(true), poolsize_(poolsize)
	{
	}
	~Pool()
	{
		MutexLockGuard guard(mutex_);
		enableReturn_ = false; 
		for (int i = 0; i < datas_.size(); ++i)
		{
			datas_.at(i)->unregisterPool();
		}
		// LOG_DEBUG << "~Pool, size: "<< datas_.size();		
	}

	class D
	{
	public:

		void operator()(T* data)
		{
			// // LOG_DEBUG << "D callback";
			Pool<T>* p = data->getPool();
			if(p == NULL)
			{
				delete data;
				data = NULL;
				return;
			}
			data->registerToPool(p);
			// shared_ptr<T> pd(data, D());
			// p->addToPool(pd);
		}

	};

	void addToPool(T* data)
	{
		//fix me: shared_from_this()
		if(!enableReturn_)
			return;
		MutexLockGuard guard(mutex_);
		if(datas_.size() >= poolsize_)
		{
			delete data;
			data = NULL;
			return;
		}
		shared_ptr<T> pd(data, D());
		// D* deleter = get_deleter<D, T>(pd);
		// assert(deleter == NULL);
		// // LOG_DEBUG << "pd reference: " << pd.use_count();
		assert(pd.get() != NULL);
		// shared_ptr<T> p(pd.get(), D());
		// // LOG_DEBUG << "p reference: " << p.use_count();
//		data.reset(data.get(), D());
		datas_.push_back(pd);
		// LOG_DEBUG << "move in a data, residual size: "<< datas_.size();
	}

	shared_ptr<T> getData()
	{
		//fix me: mutex
		assert(enableReturn_ != false);
		MutexLockGuard guard(mutex_);
		shared_ptr<T> pb;
		if(datas_.size() < 1)
		{
			return pb;
		}
		pb = datas_.back();
		datas_.pop_back();
		// // LOG_DEBUG << "pd reference: " << pb.use_count();
		assert(pb != NULL);
		// LOG_DEBUG << "move out a data, residual size: "<< datas_.size();
		return pb;
	}

	int size()
	{
		return datas_.size();
	}

	bool avaliable()
	{
		MutexLockGuard guard(mutex_);
		//// LOG_DEBUG << datas_.size();
		return datas_.size() > 0 ? true : false;
	}

private:
	bool enableReturn_;
	std::vector< shared_ptr<T> > datas_;
	muduo::MutexLock mutex_; //guard datas_
	int 	poolsize_;
};

}
}

#endif
